﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;

namespace Ha666.Redis
{
    public class RedisClient
    {

        private string[] hostStrings = ConfigurationManager.AppSettings["redis-server"].Split(',');

        public RedisClient()
        {
            Init();
        }

        private void Init()
        {
            for (int i = 0; i < hostStrings.Length; i++)
            {
                Hosts.Add(new RedisHost(hostStrings[i], 60));
            }
            DB = 0;
        }

        static RedisClient()
        {
            mDefaultDB = new RedisClient();
        }

        public static RedisClient GetClient(RedisClient db)
        {
            if (db == null)
                return DefaultDB;
            return db;
        }

        private static RedisClient mDefaultDB;

        public static RedisClient DefaultDB
        {
            get
            {
                return mDefaultDB;
            }
        }

        public RedisHost.ClientItem GetHost(int serverid)
        {
            RedisHost host;
            RedisHost.ClientItem client;
            host = Hosts[serverid];
            if (host.Available)
            {
                client = host.Pop();
                SelectDB(client.Client);
                return client;
            }
            else
            {
                host.Detect();
            }
            throw new Exception("host not Available!");
        }

        private IList<RedisHost> Hosts = new List<RedisHost>();

        private void SelectDB(TcpClient client)
        {
            if (client.DB != DB)
            {
                client.DB = DB;
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SELECT);
                    cmd.Add(DB.ToString());
                    using (Result result = TcpClient.Send(cmd, client))
                    {
                    }
                }
            }
        }

        public int DB
        {
            get;
            set;
        }

        public int Delete(int serverid, params string[] keys)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_DEL);
                    foreach (string key in keys)
                    {
                        cmd.Add(key);
                    }
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return int.Parse(result.ResultData.ToString());
                    }
                }
            }
        }

        public void HDEL(string key, string field, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HDEL);
                    cmd.Add(key);
                    cmd.Add(field);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {

                    }
                }
            }
        }

        public int HLEN(string key, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HLEN);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return int.Parse(result.ResultData.ToString());
                    }
                }
            }
            return 0;
        }

        public void EXPIRE(string key, long time, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_EXPIRE);
                    cmd.Add(key);
                    cmd.Add(time.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {

                    }
                }
            }
        }

        public List<string> Time(int serverid)
        {
            List<string> r = null;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_TIME);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        r = new List<string>(result.ResultDataBlock.Count);
                        foreach (ArraySegment<byte> i in result.ResultDataBlock)
                        {
                            r.Add(i.GetString());
                        }
                    }
                }
            }
            return r;
        }

        public T RANDOMKEY<T>(int serverid)
        {
            T t = default(T);
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_RANDOMKEY);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        t = (T)FromRedis(result.ResultDataBlock[0], DataType.String, typeof(T));
                    }
                }
            }
            return t;
        }

        public void Delete(IList<string> keys)
        {
            Delete(keys.ToArray());
        }

        public List<string> Keys(string match, int serverid)
        {
            List<string> r = null;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_KEYS);
                    cmd.Add(match);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        r = new List<string>(result.ResultDataBlock.Count);
                        foreach (ArraySegment<byte> i in result.ResultDataBlock)
                        {
                            r.Add(i.GetString());
                        }
                    }
                }
            }
            return r;
        }

        public int ListLength(string key, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_LLEN);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return int.Parse(result.ResultData.ToString());
                    }
                }
            }

        }

        public T ListPop<T>(string key, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_LPOP);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return (T)FromRedis(result.ResultDataBlock[0], dtype, typeof(T));
                    }
                }
            }
        }

        public T ListRemove<T>(string key, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_RPOP);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return (T)FromRedis(result.ResultDataBlock[0], dtype, typeof(T));
                    }
                }
            }
        }

        public void ListPush(string key, object value, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_LPUSH);
                    cmd.Add(key);
                    ToRedis(value, dtype, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {

                    }
                }
            }
        }

        public void SetListItem(string key, int index, object value, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_LSET);
                    cmd.Add(key);
                    cmd.Add(index.ToString());
                    ToRedis(value, dtype, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {

                    }
                }
            }
        }

        public void ListAdd(string key, object value, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_RPUSH);
                    cmd.Add(key);
                    ToRedis(value, dtype, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {

                    }
                }
            }
        }

        public IList<T> ListRange<T>(string key, int start, int end, DataType dtype, int serverid)
        {
            string cachekey = string.Format("{0}_list_{1}_{2}", key, start, end);
            IList<T> lst = null;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                lst = new List<T>();
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_LRANGE);
                    cmd.Add(key);
                    cmd.Add(start.ToString());
                    cmd.Add(end.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        foreach (ArraySegment<byte> item in result.ResultDataBlock)
                        {
                            lst.Add((T)FromRedis(item, dtype, typeof(T)));
                        }
                    }
                }
                return lst;
            }
        }

        public IList<T> ListRange<T>(string key, DataType dtype, int serverid)
        {
            return ListRange<T>(key, 0, -1, dtype, serverid);
        }

        public T GetListItem<T>(string key, int index, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_LINDEX);
                    cmd.Add(key);
                    cmd.Add(index.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return (T)FromRedis(result.ResultDataBlock[0], dtype, typeof(T));
                    }
                }
            }
        }

        public IList<T> GetFields<T>(string key, NameType[] fields, DataType type, int serverid)
        {
            List<T> result = GetResultSpace<T>(fields.Length);
            object value;
            NameType item;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                List<NameType> inputs = new List<NameType>();
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HMGET);
                    cmd.Add(key);
                    for (int i = 0; i < fields.Length; i++)
                    {
                        item = fields[i];
                        inputs.Add(item);
                        item.Index = i;
                        cmd.Add(item.Name);
                    }
                    using (Result R = TcpClient.Send(cmd, c.Client))
                    {
                        for (int i = 0; i < inputs.Count; i++)
                        {
                            item = inputs[i];
                            result[item.Index] = (T)FromRedis(R.ResultDataBlock[i], type, typeof(T));
                        }
                    }
                }
            }
            return result;
        }

        public T Hget<T>(string key, string name, DataType type, int serverid)
        {
            T t = default(T);
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HGET);
                    cmd.Add(key);
                    cmd.Add(name);
                    using (Result R = TcpClient.Send(cmd, c.Client))
                    {
                        t = (T)FromRedis(R.ResultDataBlock[0], type, typeof(T));
                    }
                }
            }
            return t;
        }

        public List<Field> GetAlls<T>(string key, DataType type, int serverid)
        {
            List<Field> result = new List<Field>();
            string k = "";
            object value;
            Field item = null;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                List<NameType> inputs = new List<NameType>();
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HGETALL);
                    cmd.Add(key);
                    using (Result R = TcpClient.Send(cmd, c.Client))
                    {
                        if (R.ResultDataBlock.Count > 0)
                            for (int i = 0; i < R.ResultDataBlock.Count; i++)
                            {
                                if (i % 2 == 0)
                                    k = (string)FromRedis(R.ResultDataBlock[i], DataType.String, Type.GetType(k));
                                else
                                {
                                    value = FromRedis(R.ResultDataBlock[i], type, typeof(T));
                                    item = new Field { Name = k, Value = value };
                                    result.Add(item);
                                }
                            }
                    }
                }
            }
            return result;
        }

        public int Exists(string key, string ke, DataType type, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HEXISTS);
                    cmd.Add(key);
                    cmd.Add(ke);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public IList<string> GetKeys(string key, DataType type, int serverid)
        {
            List<string> result = new List<string>();
            string value = "";
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HKEYS);
                    cmd.Add(key);
                    using (Result R = TcpClient.Send(cmd, c.Client))
                    {
                        if (R.ResultDataBlock.Count > 0)
                        {
                            for (int i = 0; i < R.ResultDataBlock.Count; i++)
                            {
                                value = (string)FromRedis(R.ResultDataBlock[i], type, Type.GetType(value));
                                result.Add(value);
                            }
                        }
                    }
                }
            }
            return result;
        }

        public List<T> GetVals<T>(string key, DataType type, int serverid)
        {
            List<T> result = new List<T>();
            T value;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HVALS);
                    cmd.Add(key);
                    using (Result R = TcpClient.Send(cmd, c.Client))
                    {
                        if (R.ResultDataBlock.Count > 0)
                        {
                            for (int i = 0; i < R.ResultDataBlock.Count; i++)
                            {
                                value = (T)FromRedis(R.ResultDataBlock[i], type, typeof(T));
                                result.Add(value);
                            }
                        }
                    }
                }
            }
            return result;
        }

        public IList<object> Get<T, T1>(string key, string key1, DataType type, int serverid)
        {
            return Get(new Type[] { typeof(T), typeof(T1) }, new string[] { key, key1 }, type, serverid);
        }

        public IList<object> Get<T, T1, T2>(string key, string key1, string key2, DataType type, int serverid)
        {
            return Get(new Type[] { typeof(T), typeof(T1), typeof(T2) }, new string[] { key, key1, key2 }, type, serverid);
        }

        public IList<object> Get<T, T1, T2, T3>(string key, string key1, string key2, string key3, DataType type, int serverid)
        {
            return Get(new Type[] { typeof(T), typeof(T1), typeof(T2), typeof(T3) }, new string[] { key, key1, key2, key3 }, type, serverid);
        }

        public IList<object> Get<T, T1, T2, T3, T4>(string key, string key1, string key2, string key3, string key4, DataType type, int serverid)
        {
            return Get(new Type[] { typeof(T), typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, new string[] { key, key1, key2, key3, key4 }, type, serverid);
        }

        public IList<object> Get(Type[] types, string[] keys, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                List<object> result = GetResultSpace<object>(keys.Length);
                List<NameType> _types = new List<NameType>();
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_MGET);
                    for (int i = 0; i < keys.Length; i++)
                    {
                        string key = keys[i];
                        cmd.Add(key);
                        _types.Add(new NameType(keys[i], i));
                    }
                    using (Result r = TcpClient.Send(cmd, c.Client))
                    {
                        for (int i = 0; i < _types.Count; i++)
                        {
                            object item = FromRedis(r.ResultDataBlock[i], dtype, null);
                            result[_types[i].Index] = item;
                        }
                    }
                }
                return result;
            }
        }

        private List<T> GetResultSpace<T>(int count)
        {
            List<T> result = new List<T>(count);
            for (int i = 0; i < count; i++)
            {
                result.Add(default(T));
            }
            return result;
        }

        public string Get(string key, int serverid)
        {
            return Get<string>(key, DataType.String, serverid);
        }

        public T Get<T>(string key, DataType type, int serverid)
        {
            T value = default(T);
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_GET);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultDataBlock.Count > 0)
                        {
                            value = (T)FromRedis(result.ResultDataBlock[0], type, typeof(T));
                            return value;
                        }
                    }
                }
                return default(T);
            }
        }

        public bool SetFields(string key, string name, object value, DataType type, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HMSET);
                    cmd.Add(key);
                    cmd.Add(name);
                    ToRedis(value, type, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return result.ResultData.ToString().Contains("OK");
                        }
                    }
                }
            }
            return false;
        }

        public int HSet(string key, string name, object value, DataType type, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HSET);
                    cmd.Add(key);
                    cmd.Add(name);
                    ToRedis(value, type, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        return int.Parse(result.ResultData.ToString());
                    }
                }
            }
        }

        public void Setnx(string key, Field item, DataType type, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_HSETNX);
                    cmd.Add(key);
                    cmd.Add(item.Name);
                    ToRedis(item.Value, type, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {

                    }
                }
            }
        }

        public void MSet(Field[] KValues, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_MSET);
                    foreach (Field item in KValues)
                    {
                        cmd.Add(item.Name);
                        ToRedis(item.Value, dtype, cmd);
                    }
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                    }
                }
            }
        }

        public int Incr(string key, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_INCR);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public int Decr(string key, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_DECR);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public void Set(string key, object value, DataType type, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SET);
                    cmd.Add(key);

                    ToRedis(value, type, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                    }
                }
            }
        }

        public int Zadd(string key, IEnumerable<SortField> sorts, DataType dtype, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZADD);
                    cmd.Add(key);
                    foreach (SortField item in sorts)
                    {
                        cmd.Add(item.Name.ToString());
                        ToRedis(item.Value, dtype, cmd);
                    }
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public int Zcard(string key, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZCARD);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public int Zcount(string key, int min, int max, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZCOUNT);
                    cmd.Add(key);
                    cmd.Add(min.ToString());
                    cmd.Add(max.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public HashSet<string> Zrange(string key, int start, int stop, DataType type, int serverid)
        {
            HashSet<string> sets = null;
            string value = "";
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZRANGE);
                    cmd.Add(key);
                    cmd.Add(start.ToString());
                    cmd.Add(stop.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultDataBlock.Count > 0)
                        {
                            sets = new HashSet<string>();
                            foreach (ArraySegment<byte> currentdata in result.ResultDataBlock)
                            {
                                value = (string)FromRedis(currentdata, type, Type.GetType(value));
                                sets.Add(value);
                            }
                        }
                    }
                }
            }
            return sets;
        }

        public HashSet<T> ZrangeByScore<T>(string key, long min, bool isIncludemin, int max, bool isIncludemax, DataType type, int serverid)
        {
            HashSet<T> hashSet = new HashSet<T>();
            T value = default(T);
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZRANGEBYSCORE);
                    cmd.Add(key);
                    cmd.Add(isIncludemin ? "" : "(" + min);
                    cmd.Add(isIncludemax ? "" : "(" + max);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultDataBlock.Count > 0)
                        {
                            foreach (ArraySegment<byte> currentdata in result.ResultDataBlock)
                            {
                                value = (T)FromRedis(currentdata, type, typeof(T));
                                hashSet.Add(value);
                            }
                        }
                    }
                }
            }
            return hashSet;
        }

        public HashSet<string> Zrevrange(string key, int start, int stop, DataType type, int serverid)
        {
            HashSet<string> sets = null;
            string value = "";
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZREVRANGE);
                    cmd.Add(key);
                    cmd.Add(start.ToString());
                    cmd.Add(stop.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultDataBlock.Count > 0)
                        {
                            sets = new HashSet<string>();
                            foreach (ArraySegment<byte> currentdata in result.ResultDataBlock)
                            {
                                value = (string)FromRedis(currentdata, type, Type.GetType(value));
                                sets.Add(value);
                            }
                        }
                    }
                }
            }
            return sets;
        }

        public int Zrank(string key, string member, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZRANK);
                    cmd.Add(key);
                    cmd.Add(member);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public int Zrevrank(string key, string member, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZREVRANK);
                    cmd.Add(key);
                    cmd.Add(member);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public void Zrem(string key, int member, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZREM);
                    cmd.Add(key);
                    cmd.Add(member.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                    }
                }
            }
        }

        public int Zscore(string key, string member, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_ZSCORE);
                    cmd.Add(key);
                    cmd.Add(member);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultDataBlock.Count > 0)
                        {
                            string value = "";
                            value = (string)FromRedis(result.ResultDataBlock[0], DataType.String, Type.GetType(value));
                            return int.Parse(value);
                        }
                    }
                }
            }
            return 0;
        }

        public int Sadd<T>(string key, List<T> members, DataType type, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SADD);
                    cmd.Add(key);
                    foreach (T member in members)
                        ToRedis(member, type, cmd);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public int Scard(string key, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SCARD);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public bool Sismember(string key, string member, int serverid)
        {
            int r = 0;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SISMEMBER);
                    cmd.Add(key);
                    cmd.Add(member);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            r = int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return r > 0;
        }

        public List<T> Smember<T>(string key, DataType type, int serverid)
        {
            List<T> sets = null;
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SMEMBERS);
                    cmd.Add(key);
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultDataBlock.Count > 0)
                        {
                            sets = new List<T>();
                            foreach (ArraySegment<byte> currentdata in result.ResultDataBlock)
                            {
                                sets.Add((T)FromRedis(currentdata, type, typeof(T)));
                            }
                        }
                    }
                }
            }
            return sets;
        }

        public int Srem(string key, int member, int serverid)
        {
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SREM);
                    cmd.Add(key);
                    cmd.Add(member.ToString());
                    using (Result result = TcpClient.Send(cmd, c.Client))
                    {
                        if (result.ResultData != null)
                        {
                            return int.Parse(result.ResultData.ToString());
                        }
                    }
                }
            }
            return 0;
        }

        public IList<object> Sort(string key, int? offset, int? count, string BYpattern, string GETpattern, bool ALPHA, string STOREdestination,
            SortOrderType orderby, Type type, DataType dtype, int serverid)
        {
            List<object> result = new List<object>();
            using (RedisHost.ClientItem c = GetHost(serverid))
            {
                using (Command cmd = new Command())
                {
                    cmd.Add(CONST_VALURES.REDIS_COMMAND_SORT);
                    cmd.Add(key);
                    if (!string.IsNullOrEmpty(BYpattern))
                    {
                        cmd.Add("BY");
                        cmd.Add(BYpattern);
                    }
                    if (!string.IsNullOrEmpty(GETpattern))
                    {
                        cmd.Add("GET");
                        cmd.Add(GETpattern);
                    }
                    if (offset != null)
                    {
                        cmd.Add("LIMIT");
                        cmd.Add(offset.Value.ToString());
                        cmd.Add(count == null ? "1000" : count.Value.ToString());
                    }
                    if (ALPHA)
                    {
                        cmd.Add("ALPHA");
                    }
                    cmd.Add(Enum.GetName(typeof(SortOrderType), orderby));
                    if (!string.IsNullOrEmpty(STOREdestination))
                    {
                        cmd.Add("STORE");
                        cmd.Add(STOREdestination);
                    }
                    using (Result rd = TcpClient.Send(cmd, c.Client))
                    {
                        foreach (ArraySegment<byte> item in rd.ResultDataBlock)
                        {
                            result.Add(FromRedis(item, dtype, type));
                        }
                    }
                }

            }
            return result;
        }

        private void ToRedis(object value, DataType type, Command cmd)
        {
            if (type == DataType.String)
            {
                cmd.Add((string)value);
            }
            else
            {
                cmd.AddProtobuf(value);
            }
        }

        private object FromRedis(ArraySegment<byte> data, DataType type, Type otype)
        {
            if (type == DataType.String)
            {
                return data.GetString();
            }
            else
            {
                try
                {
                    return data.GetProtobuf(otype);
                }
                catch (Exception e_)
                {
                    throw new Exception(string.Format("{0} type get error!", otype), e_);
                }
            }
        }
    }
}
